package com.kevin.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

import com.kevin.model.db.DBTableColumnModel;
import com.kevin.model.db.DBTableModel;
import com.kevin.util.CacheUtil;
import com.kevin.util.ConfigProperties;
import com.kevin.util.Utils;

import lombok.Data;
import lombok.extern.log4j.Log4j;

@Data
@Log4j
/**
 * 生成实体类的服务
 * 
 * @ClassName EntityService
 * @author <a href="mailto:donggongai@126.com" target="_blank">kevin</a>
 * @date 2016年8月24日 下午2:34:37
 *
 */
public class EntityService {
    private static int succnum = 0;
    // 常用词默认配置，index0为原始字符1为转换后字符
    private static final String[][] COMMON_WORDS_DEFAULT = { { "username", "userName" }, { "createtime", "createTime" },
            { "createby", "createBy" }, { "modifytime", "modifyTime" }, { "modifyby", "modifyBy" } };
    private static final Map<String, String> COMMON_WORDS_MAP = new HashMap<>();

    /**
     * 
     * 输出实体类
     * 
     * @Title createEntity
     * @author 吕凯
     * @date 2016年8月25日 上午10:08:21
     * @param tableList
     *            table数据包
     * @param packeage
     *            包名
     * @param dic
     *            输出目录
     * @param createDAO
     *            是否创建DAO
     * @return
     * @throws SQLException
     *             int
     */
    public static int createEntity(List<DBTableModel> tableList, String packeage, String dic, boolean createDAO) throws SQLException {
        succnum = 0;
        tableList.stream().forEach(table -> {
            List<DBTableColumnModel> tableColList = table.getColumns();
            String tableComments = table.getTableComments();
            String tableName = table.getTableName();

            exportEntity(tableComments, packeage, tableName, tableColList, dic);
            exportDAO(tableComments, packeage, tableName, dic, createDAO);
        });
        return succnum;
    }

    /**
     * 导出实体类
     * 
     * @Title exportEntity
     * @author 朱鹏程
     * @date 2016年8月23日 上午10:09:27
     * @param tableComments
     * @param dic
     *            输出目录 void
     */
    private static void exportEntity(String tableComments, String packeage, String tableName, List<DBTableColumnModel> tableColList,
            String dic) {
        packeage = dealPackageStr(packeage);
        String content = parse(tableComments, packeage, tableName, tableColList);
        File dicFile = new File(dic);
        if (!dicFile.exists()) {
            dicFile.mkdirs();
        }
        log.warn(dicFile.getAbsolutePath());
        outFile(tableName, dic, content, "Model");
    }

    private static String dealPackageStr(String packeage) {
        if (!StringUtils.isBlank(packeage) && !packeage.startsWith(".")) {
            packeage = "." + packeage;
        }
        return packeage;
    }

    /**
     * 导出DAO文件
     * 
     * @Title exportDAO
     * @author 吕凯
     * @date 2016年8月23日 上午9:22:48
     * @param tableComments
     * @param dic
     * @param createDAO
     *            void
     */
    private static void exportDAO(String tableComments, String packeage, String tableName, String dic, boolean createDAO) {
        if (createDAO) {
            packeage = dealPackageStr(packeage);
            String daoContent = "";
            StringBuffer sbDao = new StringBuffer();
            sbDao.append("package com.dao" + packeage + ";");
            sbDao.append("\r\n");
            sbDao.append("import com.dao.CreditBaseDao;");
            sbDao.append("\r\n");
            sbDao.append("import com.model" + packeage + "." + parseClassName(tableName) + "Model;");
            sbDao.append("\r\n");
            sbDao.append("\r\n");
            if (!StringUtils.isBlank(tableComments)) {
                sbDao.append("/*").append(tableComments).append("*/");
            }
            sbDao.append("\r\n");
            sbDao.append("public class " + parseClassName(tableName) + "Dao" + " extends CreditBaseDao<" + parseClassName(tableName)
                    + "Model" + ">{");
            sbDao.append("\r\n");
            sbDao.append("\r\n");
            sbDao.append("\tpublic " + parseClassName(tableName) + "Dao" + "() {");
            sbDao.append("\r\n");
            sbDao.append("\t\tsuper(\"" + tableName.toUpperCase() + "\");");
            sbDao.append("\r\n");
            sbDao.append("\t}");
            sbDao.append("\r\n");
            sbDao.append("}");
            daoContent = sbDao.toString();
            outFile(tableName, dic, daoContent, "Dao");
        }
    }

    /**
     * 导出文件
     * 
     * @Title outFile
     * @author 吕凯
     * @date 2016年8月31日 下午3:59:56
     * @param tablename
     * @param dic
     * @param daoContent
     * @param filtType
     *            void
     */
    private static void outFile(String tablename, String dic, String daoContent, String filtType) {
        try {
            FileOutputStream fwDao = new FileOutputStream(new File(dic, parseClassName(tablename) + filtType + ".java"));
            PrintWriter pwDao = new PrintWriter(new OutputStreamWriter(fwDao, "UTF-8"));
            pwDao.println(daoContent);
            pwDao.flush();
            pwDao.close();
            succnum++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析处理(生成实体类主体代码)
     */
    private static String parse(String tableComments, String packeage, String tableName, List<DBTableColumnModel> tableColList) {
        StringBuffer sb = new StringBuffer();
        sb.append("package com.model" + packeage + ";\r\n");
        sb.append("\r\n");
        sb.append("import java.io.Serializable;\r\n");
        sb.append("import java.util.Date;\r\n");
        sb.append("\r\n");
        sb.append("import lombok.Data;\r\n");
        sb.append("\r\n");
        sb.append("import com.ld.dao.annotation.Annotation.TableName;\r\n");
        sb.append("\r\n");
        sb.append("/**" + (tableComments == null ? "" : tableComments) + "(" + tableName.toUpperCase() + ")" + "*/\r\n"); // 表注释
        sb.append("@TableName(\"" + tableName + "\")\r\n");// 表注释

        sb.append("@Data");// 采用注解
        sb.append("\r\n");
        sb.append("public class " + parseClassName(tableName) + "Model implements Serializable {\r\n");
        processAllAttrs(tableName, sb, tableColList);
        sb.append("}\r\n");
        return sb.toString();

    }

    /**
     * 解析输出属性
     * 
     * @return
     */
    private static void processAllAttrs(String tableName, StringBuffer sb, List<DBTableColumnModel> tableColList) {
        // 生成序列号
        sb.append("\tprivate static final long serialVersionUID = " + Math.abs(new Random().nextLong()) + "L;\r\n");
        // 循环表字段
        for (DBTableColumnModel columnModel : tableColList) {
            if (!StringUtils.isBlank(columnModel.getRemarks())) {
                sb.append("\t/*").append(columnModel.getRemarks()).append("*/");
            }
            sb.append("\r\n");
            sb.append("\tprivate " + columnModel.getJavaDataType() + " " + columnModel.getExportColName() + ";\r\n");

        }
        sb.append("\r\n");
    }

    /**
     * 解析为符合编码规范的类名称
     * 
     * @Title parseClassName
     * @author 吕凯
     * @date 2016年8月25日 下午2:23:52
     * @param str
     * @return String
     */
    public static String parseClassName(String str) {
        return Utils.toUpperCaseFirst(parseFieldName(str));
    }

    /**
     * 解析为符合编码规范的字段名称
     * 
     * @Title parseFieldName
     * @author 吕凯
     * @date 2016年8月25日 下午2:23:19
     * @param str
     * @return String
     */

    public static String parseFieldName(String str) {
        str = str.toLowerCase();// 转换为小写
        COMMON_WORDS_MAP.clear();
        // 默认配置，可被后面的设置覆盖
        Arrays.asList(COMMON_WORDS_DEFAULT).stream().forEach(commonWordSetArrs -> {
            COMMON_WORDS_MAP.put(commonWordSetArrs[0], commonWordSetArrs[1]);
        });
        Map<String, String> commonWordsMap = null;
        try {
            commonWordsMap = CacheUtil.get(ConfigProperties.CACHE_COMMON_WORDS);
        } catch (Exception e) {
            log.error("获取常用词设置缓存失败！", e);
        }
        if (commonWordsMap != null && commonWordsMap.size() > 0) {
            COMMON_WORDS_MAP.putAll(commonWordsMap);
        }
        if (COMMON_WORDS_MAP != null && COMMON_WORDS_MAP.size() > 0 && COMMON_WORDS_MAP.containsKey(str)) {
            str = COMMON_WORDS_MAP.get(str);
            return str;
        } else {
            str = splitWordSet(str);
            return Utils.lineToHump(str);
        }
    }

    /**
     * 根据设置的单词进行划分
     * 
     * @Title splitWordSet
     * @author 吕凯
     * @date 2016年8月25日 上午11:37:29
     * @param str
     * @return String
     */
    private static String splitWordSet(String str) {
        String wordSet = ConfigProperties.getString(ConfigProperties.WORDSET);
        if (!StringUtils.isBlank(wordSet)) {
            wordSet = wordSet.replace(",", "|");
            Pattern humpPattern = Pattern.compile(wordSet);
            Matcher matcher = humpPattern.matcher(str);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
            }
            matcher.appendTail(sb);
            str = sb.toString();
            if (str.startsWith("_")) {
                str = StringUtils.substringAfter(str, "_");
            }
        }
        return str;
    }

    /**
     * 执行方法
     */
    public static void main(String[] args) throws SQLException {
        String source = "mobilephone";
        System.out.println(parseFieldName(source));

    }
}
